home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / benchmarks / itc / sas / sas.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-30  |  42.9 KB  |  1,786 lines

  1. /* $Header: sas.c,v 3.15 88/10/18 16:34:39 hilfingr Exp $ */
  2.  
  3. /* Sas assembler for SPUR */
  4.  
  5. /* Copyright (c) 1987 by the Regents of the University of California.  
  6.  * All rights reserved.  
  7.  *
  8.  * Author: P. N. Hilfinger
  9.  */
  10.  
  11. static char *rcsid = "$Header: sas.c,v 3.15 88/10/18 16:34:39 hilfingr Exp $";
  12.  
  13. #include <stdio.h>
  14. #include <sys/file.h>
  15. #include <string.h>
  16. #include <signal.h>
  17. #include <sys/wait.h>
  18. #include "sas.h"
  19. #include "parser.h"
  20. #include "a.out.h"
  21.  
  22. #define MAXEXPRTERMS  1000    /* Maximum number of expression nodes for 
  23.                  * single stmt. */
  24. #define SEGMENTINCR   (1<<14)    /* Size by which to step up buffer for 
  25.                  * assembler text or data segment */
  26. #define MAXFILENAMELENGTH 100   /* Maximum length of file name handled. */
  27. #define MAXPREPROCESSARGS 100   /* Maximum number of arguments to /lib/cpp */
  28. #define MAXTEMPLABELS     100   /* Maximum temporary label number + 1 */
  29.  
  30. #define IEEE_ARITH 1
  31. #define VAX_ARITH 2
  32. #define OTHER_ARITH 3
  33.  
  34. #ifdef SPUR
  35. #define FLOAT_ARITH IEEE_ARITH
  36. #endif
  37.  
  38. #ifdef SUN
  39. #define FLOAT_ARITH IEEE_ARITH
  40. #define BYTES_BIG_ENDIAN
  41. #endif
  42.  
  43. #ifdef VAX
  44. #define FLOAT_ARITH VAX_ARITH
  45. #endif
  46.  
  47. #define FIRST_TEXT_SEG RP_SEG0
  48. #define FIRST_DATA_SEG RP_SEG0+3
  49. #define FIRST_SHARED_DATA_SEG RP_SEG0+7
  50. #define BSS_SEG    RP_SEG0+6
  51. #define SBSS_SEG   RP_SEG0+9
  52.  
  53. struct _segmentDescType {
  54.     char *mem;            /* Start of memory */
  55.     int size;            /* Maximum size */
  56. };
  57.  
  58. typedef struct _segmentDescType segmentDescType; 
  59.  
  60. static unsigned int
  61.            LC[RP_SEGLAST+1],         /* Location counters for each 
  62.                      * segment. */
  63.            segmentSize[RP_SEGLAST+1],    /* Current size for each segment. */
  64.            segmentStart[RP_SEGLAST+1];    /* Starting place in file for each 
  65.                      * segment */
  66.  
  67. #define NUM_ASM_SEGS  10    /* Number of segments seen by programmer */
  68.  
  69. static segmentDescType segment[RP_SEGLAST+1];
  70.                                 /* Region pointers for each segment. */
  71.  
  72. static symbolType *segmentSym[RP_SEGLAST+1]; 
  73.                                 /* Symbols for the starts of the TEXTx, DATAx, 
  74.                  * SDATAx, and BSS regions. */
  75.  
  76. static segmentDescType
  77.                reloc,        /* Output relocation data */
  78.                relocExpr,    /* Relocation expression data */
  79.                strings;         /* Output string table */
  80.  
  81. static struct nlist *symbols;  /* Output symbol area */
  82.  
  83. static unsigned int disallowedOpcodeMask;
  84.                                /* Opcodes that yield non-zero when &'ed with 
  85.                 * this mask are to be disallowed. */
  86. static bool nativeFloatSwitch;
  87.                 /* True iff floating-point constants are to */
  88.                 /* be in host native mode for simulations. */
  89.  
  90. /* Segment sizes in bytes */
  91. static unsigned int
  92.     relocSize,
  93.     relocExprSize,
  94.     symbolsSize,
  95.     stringsSize;
  96.  
  97. extern void
  98.     initTempLabels(),
  99.     resetTempLabels();
  100.  
  101.         /* Various utilities */
  102. #ifndef BYTES_BIG_ENDIAN
  103.  
  104. #define bcopy2(s1, s2, offset, n) \
  105.     (void) bcopy((char *) (s1), ((char *) (s2)) + (offset), (int) (n))
  106.  
  107. #define numcopy(s1, s2, offset, n) \
  108. {\
  109.     int _numcopy_ = (s1); \
  110.     (void) bcopy((char *) &_numcopy_, ((char *) (s2)) + (offset), (int) (n)); \
  111.     }
  112.  
  113. #else
  114.  
  115. #define bcopy2(s1, s2, offset, n) \
  116. {\
  117.      int __n = (n); \
  118.      int __offset = (offset); \
  119.      char *__s1 = (char *)(s1), *__s2 = (char *)(s2); \
  120.      while (__n -- > 0) { \
  121.          __s2[(__offset & ~3) + 3 - (__offset & 3)] = *__s1++; \
  122.      __offset++; \
  123.      } \
  124. }
  125.  
  126. #define numcopy(x, s2, offset, n) \
  127. {\
  128.      int __n = (n); \
  129.      int __offset = (offset); \
  130.      unsigned int __x = (x); \
  131.      char *__s2 = (char *)(s2); \
  132.      while (__n -- > 0) { \
  133.          __s2[(__offset & ~3) + 3 - (__offset & 3)] = __x & 0xff; \
  134.      __offset++; \
  135.      __x >>= 8;\
  136.      }\
  137. }
  138.  
  139. #endif
  140.  
  141. int errorCount;            /* Cumulative error count. */
  142.  
  143. void
  144. errorHeader()
  145.      /* Print prefix of error message. */
  146. {
  147.     if (linecount == 0) {
  148.     (void) fprintf(stderr, "\"%s\", line 0: ", filename);
  149.     }
  150.     else {
  151.     (void) fprintf(stderr, "\"%s\", line %d-%d: ", filename, linecount-1, 
  152.                linecount);
  153.     }
  154. }
  155.  
  156.         /* Expandable segment utilities */
  157.  
  158. void
  159. initSegment(s, noSpace)
  160.      segmentDescType *s;
  161.      bool noSpace;
  162.      /* Initialize segment s.  Allocate no space if noSpace. */
  163. {
  164.     if (noSpace) {
  165.     s -> size = -1;
  166.     s -> mem = NULL;
  167.     }
  168.     else {
  169.     s->size =  SEGMENTINCR;
  170.     s->mem  =  (char *) malloc(SEGMENTINCR);
  171.     (void) bzero((char *) (s -> mem), SEGMENTINCR);
  172.     if (s->mem == NULL) {
  173.         ErrorMsg
  174.         "Fatal error: out of memory."
  175.         EndMsg;
  176.         exit2(1);
  177.     }
  178.     }
  179. }
  180.  
  181. void
  182. expandSegment(s,n)
  183.      segmentDescType *s;
  184.      unsigned int n;
  185.      /* Expand segment s to at least size n. If the segment is a dummy segment
  186.       * (containing no space), this operation has no effect. */
  187. {
  188.     char *new;
  189.  
  190.     if (s->size == -1 || s->size >= n) return;
  191.     n = ((n+SEGMENTINCR-1) / SEGMENTINCR) * SEGMENTINCR;
  192.     new = (char *) malloc(n);
  193.     if (new == NULL) {
  194.     ErrorMsg
  195.         "Fatal error: out of memory."
  196.         EndMsg;
  197.     exit2(1);
  198.     }
  199.     (void) bcopy( (char *) s -> mem, (char *) new, (int) (s -> size));
  200.     (void) bzero( (int) (s -> size) + (char *) new, (int) (n - s -> size));
  201.     (void) free((char *) s->mem);
  202.     s->mem = new;
  203.     s->size = n;
  204. }    
  205.  
  206. #define checkSeg(s,n)   \
  207.     /* Check that segment s has at least n bytes */  \
  208.     { if ((s).size < n) expandSegment(&(s), n); }
  209.  
  210. #define checkThisSeg(n) \
  211.     /* Check that current segment has at least n bytes at current location */ \
  212.     {  checkSeg(segment[currentSegment], LC[currentSegment] + n); }
  213.  
  214.              /* Expressions */
  215.  
  216. static exprType exprSpace[MAXEXPRTERMS];
  217. static exprType *nextExpr;    /* Pointer to next free expression node. */
  218.  
  219. exprType *
  220. newExpr()
  221.      /* Allocate new expression node. */
  222. {
  223.     if (nextExpr == exprSpace) {
  224.     ErrorMsg  "Fatal assembler error: statement too complex." EndMsg;
  225.     exit2(1);
  226.     }
  227.     return nextExpr--;
  228. }
  229.  
  230. void
  231. initExprs()
  232.      /* Initialize expression allocator, freeing all space. */
  233. {
  234.     nextExpr = &exprSpace[MAXEXPRTERMS-1];
  235. }
  236.     
  237. exprType *
  238. numToExpr(n)
  239.      unsigned int n;
  240.      /* Convert integer n to an expression */
  241. {
  242.     exprType *e;
  243.  
  244.     e = newExpr();
  245.     e -> class = MANIFEST_INT;
  246.     e -> v.value = n;
  247.     e -> left = e -> right = NULL;
  248.     return e;
  249. }
  250.  
  251. exprType *
  252. symToExpr(s)
  253.      symbolType *s;
  254.      /* Convert symbol s to an expression. */
  255. {
  256.     exprType *e;
  257.  
  258.     switch (s -> type & N_TYPE) {
  259.     case N_ABS:
  260.     e = numToExpr(s -> value);
  261.     break;
  262.     case N_TEXT:
  263.     case N_DATA:
  264.     case N_BSS:
  265.     case N_SDATA:
  266.     case N_SBSS:
  267.     e = newExpr();
  268.     e -> class = SYM_EXPR;
  269.     e -> v.sym = segmentSym[s -> segment];
  270.     e -> offset = s -> value;
  271.     e -> left = e -> right = NULL;
  272.     break;
  273.     default:
  274.     e = newExpr();
  275.     e -> class = SYM_EXPR;
  276.     e -> v.sym = s;
  277.     e -> offset = 0;
  278.     e -> left = e -> right = NULL;
  279.     break;
  280.     }
  281.     return e;
  282. }
  283.  
  284. exprType *
  285. consUnaryExpr(op, op1)
  286.      unsigned int op;
  287.      exprType *op1;
  288.      /* Create an expression representing op applied to op1. */
  289. {
  290.     if (op1 -> class == MANIFEST_INT)
  291.     switch (op) {
  292.     case '-':
  293.         return numToExpr( -(op1 -> v.value) );
  294.     case '~':
  295.         return numToExpr(~op1 -> v.value);
  296.     default:
  297.         ErrorMsg  "Internal assembler error: bad operator." EndMsg;
  298.         exit2(1);  /* Should not get here. */
  299.         return nullExpr;
  300.     }
  301.     else {
  302.     exprType *e = newExpr();
  303.     e -> class = UNARY_EXPR;
  304.     e -> v.opcode = op;
  305.     e -> left = op1;
  306.     e -> right = NULL;
  307.     return e;
  308.     }
  309. }
  310.  
  311. exprType *
  312. consBinaryExpr(op, op1, op2)
  313.      unsigned int op;
  314.      exprType *op1, *op2;
  315.      /* Return expression representing binary operation op applied to op1 and 
  316.     op2. */
  317. {
  318.     exprClassType op1Class = op1 -> class,
  319.                   op2Class = op2 -> class;
  320.  
  321.     if (op1Class == MANIFEST_INT && op2Class == MANIFEST_INT)
  322.     switch (op) {
  323.     case '+':
  324.         return numToExpr(op1->v.value + op2->v.value);
  325.     case '-':
  326.         return numToExpr(op1->v.value - op2->v.value);
  327.     case '*':
  328.         return numToExpr(op1->v.value * op2->v.value);
  329.     case '/':
  330.         return numToExpr(op1-> v.value / op2->v.value);
  331.     case LSHIFT:
  332.         return numToExpr(op1->v.value << op2->v.value);
  333.     case RSHIFT:
  334.         return numToExpr(op1->v.value >> op2->v.value);
  335.     case '&':
  336.         return numToExpr(op1->v.value & op2->v.value);
  337.     case '|':
  338.         return numToExpr(op1->v.value | op2->v.value);
  339.     case '^':
  340.         return numToExpr(op1->v.value ^ op2->v.value);
  341.     default:
  342.         ErrorMsg "Internal assembler error: bad operator." EndMsg;
  343.         exit2(1);
  344.         return nullExpr;
  345.     }
  346.     else if ((op == '+' || op == '-') && 
  347.          op1Class == SYM_EXPR && op2Class == MANIFEST_INT) {
  348.     if (op == '+') op1 -> offset += op2 -> v.value;
  349.     else           op1 -> offset -= op2 -> v.value;
  350.     return op1;
  351.     }
  352.     else if (op == '+' && op2Class == SYM_EXPR && op1Class == MANIFEST_INT) {
  353.     op2 -> offset += op1 -> v.value;
  354.     return op2;
  355.     }
  356.     else if (   op == '-'
  357.          && op1Class == SYM_EXPR && op2Class == SYM_EXPR 
  358.          && op1 -> v.sym == op2 -> v.sym) {
  359.     op1 -> class = MANIFEST_INT;
  360.     op1 -> v.value = op1 -> offset - op2 -> offset;
  361.     return op1;
  362.     }
  363.     else {
  364.     exprType *e = newExpr();
  365.  
  366.     e -> class = BINARY_EXPR;
  367.     e -> v.opcode = op;
  368.     e -> left = op1; e -> right = op2;
  369.     return e;
  370.     }
  371. }
  372.  
  373. exprType *
  374. pointExpr()
  375.      /* Return expression for `point' */
  376. {
  377.     exprType *e = newExpr();
  378.     e -> class = SYM_EXPR;
  379.     e -> v.sym = segmentSym[currentSegment];
  380.     e -> offset = LC[currentSegment];
  381.     e -> left = e -> right = NULL;
  382.     return e;
  383. }
  384.  
  385.             /* Temporary labels */
  386.  
  387. static struct {
  388.     int number;        /* Number for numeric temp, or -1 for non-numeric. */
  389.     symbolType *sym;    /* Symbol for non-numeric temp. */
  390.     int segment;    /* Segment number of defined label. */
  391.     int offset;        /* Offset from start of segment of defined label. */
  392. } backTemps[MAXTEMPLABELS];  /* Data on backwards numeric temps. */
  393.  
  394. static struct {
  395.     int number;        /* Number for numeric temp, or -1 for non-numeric. */
  396.     symbolType *sym;    /* Symbol for non-numeric temp. */
  397.     symbolType *label;  /* Label inserted in program for current occurrence of
  398.              * this this temporary label. */
  399. } forwardTemps[MAXTEMPLABELS];
  400.                         /* Symbols assigned to used, but as yet undefined
  401.              * temporary labels.  Each entry is NULL if no 
  402.              * outstanding forward reference to that label. */
  403.  
  404. int numBckwdTemps, numFwdTemps;   /* Number of active temporary labels in each
  405.                      direction */
  406.  
  407. void
  408. initTempLabels()
  409. {
  410.     numBckwdTemps = numFwdTemps = 0;
  411. }
  412.  
  413. void
  414. resetTempLabels()
  415. {
  416.     int i;
  417.     for (i = 0; i < numFwdTemps; i++) {
  418.     if (forwardTemps[i].number != -1) {
  419.         ErrorMsg 
  420.         "Forward-referenced temporary label %d undefined.", i 
  421.             EndMsg;
  422.     }
  423.     else { 
  424.         ErrorMsg 
  425.         "Forward-referenced temporary label %s undefined.", 
  426.                  forwardTemps[i].sym->string
  427.              EndMsg;
  428.     }
  429.     }
  430.     numFwdTemps = numBckwdTemps = 0;
  431. }
  432.  
  433. void
  434. DefineTempLabel(m, sym)
  435.      int m;
  436.      symbolType *sym;
  437.      /* Create definition for temporary label m if sym is NULL,
  438.       * or symbol sym, if m is -1. */
  439. {
  440.     int n;
  441.  
  442.     if (numBckwdTemps >= MAXTEMPLABELS) {
  443.     ErrorMsg "Too many temporary labels." EndMsg;        
  444.     return;
  445.     }
  446.  
  447.     backTemps[numBckwdTemps].segment = currentSegment;
  448.     backTemps[numBckwdTemps].offset = LC[currentSegment];
  449.     backTemps[numBckwdTemps].number = m;
  450.     backTemps[numBckwdTemps].sym    = sym;
  451.     for (n = 0; backTemps[n].number != m || backTemps[n].sym != sym; n++);
  452.     backTemps[n] = backTemps[numBckwdTemps];
  453.     if (n == numBckwdTemps) numBckwdTemps++;
  454.  
  455.     for (n = 0; n < numFwdTemps; n++) {
  456.     if (forwardTemps[n].number == m && forwardTemps[n].sym == sym) {
  457.         forwardTemps[n].label -> segment = currentSegment;
  458.         forwardTemps[n].label -> value = LC[currentSegment];
  459.         forwardTemps[n].label -> type = 
  460.         segmentToType(currentSegment);
  461.         forwardTemps[n] = forwardTemps[--numFwdTemps];
  462.         break;
  463.     }
  464.     }
  465. }
  466.  
  467. exprType *
  468. fwdTempLabelToExpr(m, sym)
  469.      int m;
  470.      symbolType *sym;
  471.      /* Return expression corresponding to temp label n next defined */
  472. {
  473.     int n;
  474.  
  475.     if (numFwdTemps >= MAXTEMPLABELS) {
  476.     ErrorMsg "Too many temporary labels." EndMsg;
  477.     return numToExpr(0);
  478.     }
  479.     forwardTemps[numFwdTemps].number = m; forwardTemps[numFwdTemps].sym = sym;
  480.     forwardTemps[numFwdTemps].label = NULL;
  481.     for (n = 0; forwardTemps[n].number != m || forwardTemps[n].sym != sym; n++)
  482.     ;
  483.     if (n == numFwdTemps) {
  484.     symbolType *label = newSymbol("", N_UNDF, 0, 0);
  485.     forwardTemps[n].label = label;
  486.     assignId(label);
  487.     numFwdTemps++;
  488.     }
  489.     return symToExpr(forwardTemps[n].label);
  490. }
  491.  
  492. exprType *
  493. bckwdTempLabelToExpr(m,sym)
  494.      int m;
  495.      symbolType *sym;
  496.      /* Return expression corresponding to previously defined temporary 
  497.     label n. */
  498. {
  499.     int n;
  500.  
  501.     for (n = 0; 
  502.      n < numBckwdTemps && (backTemps[n].number != m 
  503.                    || backTemps[n].sym != sym);
  504.      n++);
  505.  
  506.     if (n == numBckwdTemps) {
  507.     ErrorMsg "Temporary label not previously defined." EndMsg;
  508.     return numToExpr(0);
  509.     }
  510.     else {
  511.     exprType *e = newExpr();
  512.  
  513.     e -> class = SYM_EXPR;
  514.     e -> v.sym = segmentSym[backTemps[n].segment];
  515.     e -> offset = backTemps[n].offset;
  516.     e -> left = e -> right = nullExpr;
  517.     return e;
  518.     }
  519. }
  520.  
  521.             /* Instruction emission */
  522.  
  523. #define checkOpcode(opcode)  \
  524.     if ((opcode) & disallowedOpcodeMask) { \
  525.         WarningMsg "Warning: operation only allowed on simulator." EndMsg; \
  526.     } \
  527.     (opcode) &= ~instModifierBits;
  528.  
  529. void
  530. emitInst(inst) 
  531.     unsigned int inst;
  532.     /* Output instruction inst in current segment. 
  533.        LC[currentSegment] must be divisible by 4 */
  534. {
  535.     if (segment[currentSegment].size == -1) {
  536.     ErrorMsg "Attempt to generate code in uninitialized segment." EndMsg;
  537.     }
  538.     else {
  539.     checkThisSeg(sizeof(unsigned int));
  540.     * (unsigned int *) (segment[currentSegment].mem + LC[currentSegment]) 
  541.         = inst;
  542.     LC[currentSegment] += sizeof(unsigned int);
  543.     }
  544. }
  545.  
  546. bool
  547. isValidConstant(n)
  548.      unsigned int n;
  549.      /* True iff n is a valid rc or sc immediate. */
  550. {
  551.     return ( (n & ~immedMask) + ((n & immedSign) << 1) == 0);
  552. }
  553.  
  554. void
  555. formConstant(n, r)
  556.      unsigned int n;
  557.      int r;
  558.      /* Form the constant n in register r. */
  559. {
  560.     if (n > maxComputedLiteral && n < minComputedLiteral) {
  561.  
  562.     emitInst( (unsigned int) rd_specialOpcode << opCodePosn | 
  563.           pc_sreg << src1Posn | r<<destPosn );
  564.         /* rd_special  r,pc */
  565.     emitInst( (unsigned int) jump_regOpcode << opCodePosn | r << src1Posn 
  566.           | immedFlag | 0x10 );
  567.         /* jump_reg    r,16 */
  568.     emitInst( (unsigned int) ld_32Opcode << opCodePosn
  569.          | r << destPosn | r << src1Posn | immedFlag | 0x0c );
  570.         /* ld_32       r,r,$12 */
  571.     emitInst( n );
  572.         /* .long    n */
  573.     emitInst( (unsigned int) add_ntOpcode << opCodePosn );
  574.         /* nop */
  575.     }
  576.     else {
  577.     unsigned int top;
  578.     int shift, lowzeros, i;
  579.     
  580.     lowzeros = 0, shift = 0;
  581.     if (n >= 0x80000000) {
  582.         top = ~n;
  583.         while(top > maxUnsignedRcLit) {
  584.         if (lowzeros == shift && (top & 1) == 1) 
  585.             lowzeros++;
  586.         top >>= 1;
  587.         shift++;
  588.         }
  589.         top = ~top;
  590.     }
  591.     else {
  592.         top = n;
  593.         while (top > maxUnsignedRcLit) {
  594.         if (lowzeros == shift && (top & 1) == 0)
  595.             lowzeros++;
  596.         top >>= 1;
  597.         shift++;
  598.         }
  599.     }
  600.  
  601.     emitInst((unsigned int) add_ntOpcode << opCodePosn | r << destPosn 
  602.          | immedFlag | top & immedMask);
  603.          /* Put top part in r */
  604.     for (i = shift; i > 0; i -= 3)
  605.         emitInst((unsigned int) sllOpcode << opCodePosn | r << destPosn
  606.              | r << src1Posn | immedFlag | (i >= 3 ? 3 : i));
  607.             /* Shift left */
  608.     if (lowzeros != shift) {
  609.         emitInst(orOpcode << opCodePosn | r << destPosn | r << src1Posn |
  610.              immedFlag | (n ^ (top << shift)));
  611.     }
  612.     }
  613. }
  614.  
  615. void
  616. SetOrg(e)
  617.      exprType *e;
  618.      /* Set origin to value of e. */
  619. {
  620.     unsigned int offset;
  621.  
  622.     if (LC[currentSegment] > segmentSize[currentSegment])
  623.     segmentSize[currentSegment] = LC[currentSegment];
  624.     if (e -> class == MANIFEST_INT)
  625.     offset = e -> v.value;
  626.     else if (e -> class == SYM_EXPR && e -> v.sym -> id == currentSegment)
  627.     offset = e -> offset;
  628.     else {
  629.     ErrorMsg
  630.         "Improper change of origin."
  631.         EndMsg;
  632.     return;
  633.     }
  634.     if (offset > segmentSize[currentSegment]) {
  635.     segmentSize[currentSegment] = offset;
  636.     checkSeg(segment[currentSegment], offset);
  637.     }
  638.     LC[currentSegment] = offset;
  639. }
  640.  
  641. void
  642. leaveSpace(e)
  643.      exprType *e;
  644.      /* Increase the current LC by the value of e >= 0, thus allocating space.
  645.       */
  646. {
  647.     unsigned int newLC;
  648.     if (e -> class != MANIFEST_INT) {
  649.     ErrorMsg
  650.         "Improper allocation size."
  651.     EndMsg;
  652.     return;
  653.     }
  654.     newLC = e -> v.value + LC[currentSegment];
  655.     if (newLC > segmentSize[currentSegment]) {
  656.     segmentSize[currentSegment] = newLC;
  657.     checkSeg(segment[currentSegment], newLC);
  658.     }
  659.     LC[currentSegment] = newLC;
  660. }
  661.  
  662. void
  663. emitStab(string, ntype, nother, ndesc, nvalue)
  664.      char *string;
  665.      unsigned int ntype, nother, ndesc;
  666.      exprType *nvalue;
  667.      /* Enter debugging symbol into symbol table.  String is optional string
  668.       * data for n_un field; ntype, nother, ndesc, and nvalue are n_type,
  669.       * n_other, n_desc, and n_value fields in symbol.  In the case that
  670.       * nvalue is null, this assumes that ntype is appropriate to the current
  671.       * segment. */
  672. {
  673.     symbolType *s = newSymbol(string, N_UNDF | ntype & ~N_TYPE, nother, ndesc);
  674.  
  675.     assignId(s);
  676.     if (nvalue == nullExpr) {
  677.     struct relocation_info *item;
  678.  
  679.     checkSeg(reloc, relocSize+sizeof(struct relocation_info));
  680.     item = (struct relocation_info *) (reloc.mem + relocSize);
  681.     item->r_address = (unsigned int) ((s -> id) * sizeof(struct nlist));
  682.     item->r_segment = RP_SYMBOLS;
  683.     item->r_word = 0;
  684.     item->r_length = RP_32;
  685.     item->r_extra = 0;
  686.     item->r_reltype = RP_RSYM;
  687.     item->r_expr = currentSegment - RP_SEG0;
  688.     relocSize += sizeof(struct relocation_info);
  689.  
  690.     s -> value = LC[currentSegment];
  691.     }
  692.     else 
  693.     emitReloc(RP_SYMBOLS,
  694.           (unsigned int) ((s -> id) * sizeof(struct nlist)),
  695.           RP_32, 0, nvalue);
  696. }
  697.  
  698. void
  699. emitBytes(str, len)
  700.      char *str;
  701.      int len;
  702.      /* Place len bytes from str in current segment at current LC.  Move up LC.
  703.       */
  704. {
  705.     checkSeg(segment[currentSegment], LC[currentSegment]+len);
  706.     if (segment[currentSegment].size == -1) {
  707.     ErrorMsg 
  708.         "Attempt to generate code or data in uninitialized segment." 
  709.         EndMsg;
  710.     }
  711.     else {
  712.     bcopy2(str, segment[currentSegment].mem, LC[currentSegment], len);
  713.     LC[currentSegment] += len;
  714.     }
  715. }
  716.  
  717. void
  718. emitExpr(e, size)
  719.      exprType *e;
  720.      int size;
  721.      /* Insert constant with value of expression e in current segment at 
  722.       * current LC.  Constant is size bytes long. */
  723. {
  724.     checkSeg(segment[currentSegment], LC[currentSegment]+size);
  725.     if (segment[currentSegment].size == -1) {
  726.     ErrorMsg 
  727.         "Attempt to generate code or data in uninitialized segment." 
  728.         EndMsg;
  729.     return;
  730.     }
  731.     if (e -> class == MANIFEST_INT) {
  732.         numcopy(e -> v.value, segment[currentSegment].mem, LC[currentSegment],
  733.         size);
  734.     }
  735.     else {
  736.     numcopy(0, segment[currentSegment].mem, LC[currentSegment], size);
  737.     emitReloc(currentSegment, LC[currentSegment], 
  738.           (size == 8 ? RP_LOW8 : size == 16 ? RP_LOW16 : RP_32),
  739.           0, e);
  740.     }
  741.     LC[currentSegment] += size;
  742. }
  743.  
  744. #ifdef VAX
  745. typedef struct  {
  746.     unsigned int
  747.     frac : 23,
  748.     exponent : 8,
  749.     sign : 1;
  750. } SpurSingleFloat;
  751.  
  752. typedef struct  {
  753.     unsigned int
  754.     frac1 : 20,
  755.     exponent : 11,
  756.     sign : 1;
  757.     unsigned int
  758.     frac0;
  759. } SpurDoubleFloat;
  760. #else
  761. typedef float SpurSingleFloat;
  762. typedef double SpurDoubleFloat;
  763. #endif
  764.  
  765. #ifdef VAX
  766. struct SINGLEFLOAT {
  767.     unsigned int
  768.     frac1 : 7,
  769.     exponent : 8,
  770.     sign : 1,
  771.         frac0 : 16;
  772. };
  773.  
  774. struct DOUBLEFLOAT {
  775.     unsigned int
  776.     frac3 : 4,
  777.     exponent : 11,
  778.     sign : 1,
  779.     frac2 : 16;
  780.     unsigned int
  781.     frac1 : 16,
  782.     frac0 : 16;
  783. };
  784. #endif        
  785.  
  786. SpurSingleFloat
  787. toSingleIEEE(x, len)
  788.      char *x;
  789.      int len;
  790.      /* Convert x (len bytes long)  to IEEE single-precision form for SPUR, 
  791.       * with host's byte order. */
  792. {
  793.     char buffer[100];
  794.     int sign;
  795.     float y;
  796.  
  797.     sign = 0;
  798.     if (x[0] == '-') 
  799.     sign = 1, x++;
  800.     else if (x[0] == '+')
  801.     x++;
  802.  
  803.     (void) strncpy(buffer, x, len);
  804.     buffer[len] = '\0';
  805.     (void) sscanf(x, "%e", &y);
  806.  
  807. #if FLOAT_ARITH == IEEE_ARITH
  808.     return sign ? -y : y;
  809. #endif
  810.  
  811. #if FLOAT_ARITH == VAX_ARITH
  812.     {
  813.     SpurSingleFloat z;
  814.     struct SINGLEFLOAT *p = (struct SINGLEFLOAT *) &y;
  815.     
  816.     if (p -> exponent == 0)
  817.         z.exponent = 0, z.frac = 0;
  818.     else if (p -> exponent == 1)
  819.         z.exponent = 0, 
  820.         z.frac = p -> frac0 >> 2 | p -> frac1 << 14 | 1 << 21;
  821.     else if (p -> exponent == 2)
  822.         z.exponent = 0,
  823.         z.frac = p -> frac0 >> 1 | p -> frac1 << 15 | 1 << 22;
  824.     else
  825.         z.exponent = p -> exponent - 1, 
  826.         z.frac = p -> frac0 | p -> frac1 << 16;
  827.     z.sign = sign;
  828.     return z;
  829.     }    
  830. #endif
  831.  
  832. #if FLOAT_ARITH == OTHER_ARITH
  833.     ErrorMsg "Floating point operands not yet supported." EndMsg;
  834.     return 0.0;
  835. #endif
  836. }
  837.  
  838. SpurDoubleFloat
  839. toDoubleIEEE(x, len)
  840.      char *x;
  841.      int len;
  842.      /* Convert x (len bytes long)  to IEEE single-precision form for SPUR, 
  843.       * in the SPUR byte order.  */
  844. {
  845.     char buffer[100];
  846.     int sign;
  847.     double y;
  848.  
  849.     sign = 0;
  850.     if (x[0] == '-') 
  851.     sign = 1, x++;
  852.     else if (x[0] == '+')
  853.     x++;
  854.  
  855.     (void) strncpy(buffer, x, len);
  856.     buffer[len] = '\0';
  857.     (void) sscanf(x, "%le", &y);
  858.  
  859. #if FLOAT_ARITH == IEEE_ARITH
  860.     return sign ? -y : y;
  861. #endif
  862.  
  863. #if FLOAT_ARITH == VAX_ARITH
  864.     {
  865.     struct DOUBLEFLOAT *p = (struct DOUBLEFLOAT *) &y;
  866.     SpurDoubleFloat z;
  867.     
  868.     if (p -> exponent == 0)
  869.         z.exponent = 0, z.frac1 = 0, z.frac0 = 0;
  870.     else if (p -> exponent == 1)
  871.         z.exponent = 0, 
  872.         z.frac1 = p -> frac3 << 14 | p -> frac2 >> 2 | 1 << 18,
  873.         z.frac0 = (p -> frac2 & 3) << 30
  874.               | p -> frac1 << 13| p -> frac0 >> 2;
  875.     else if (p -> exponent == 2)
  876.         z.exponent = 0, 
  877.         z.frac1 = p -> frac3 << 15 | p -> frac2 >> 1 | 1 << 19,
  878.         z.frac0 = (p -> frac2 & 1) << 31
  879.               | p -> frac1 << 15 | p -> frac0 >> 1;
  880.     else
  881.         z.exponent = p -> exponent - 1,
  882.         z.frac1 = p -> frac3 << 16 | p -> frac2,
  883.         z.frac0 = p -> frac1 << 16 | p -> frac0;
  884.     z.sign = sign;
  885.     return z;
  886.     }    
  887. #endif
  888.  
  889. #if FLOAT_ARITH == OTHER_ARITH
  890.     ErrorMsg "Floating point operands not yet supported." EndMsg;
  891. #endif
  892. }
  893.  
  894. void
  895. emitFloat(v, l, size)
  896.      char *v;
  897.      int l;
  898.      int size;
  899.      /* Emit l-byte floating point literal v in current segment as a
  900.       * floating point number of given size. */
  901. {
  902.     if (segment[currentSegment].size == -1) {
  903.     ErrorMsg 
  904.         "Attempt to generate code or data in uninitialized segment." 
  905.         EndMsg;
  906.     return;
  907.     }
  908.  
  909.     checkSeg(segment[currentSegment], LC[currentSegment]+size);
  910.  
  911.     if (size == SINGLE) {
  912.     if (nativeFloatSwitch) {
  913.         float x;
  914.         (void) sscanf(v, "%e", &x);
  915.         bcopy((char *) &x, 
  916.           (char *) (segment[currentSegment].mem + LC[currentSegment]),
  917.           size);
  918.     }
  919.     else {
  920.         SpurSingleFloat x;
  921.         x = toSingleIEEE(v,l);
  922.         bcopy((char *) &x, 
  923.           (char *) (segment[currentSegment].mem + LC[currentSegment]),
  924.           size);
  925.     }
  926.     }
  927.     else {
  928.     if (nativeFloatSwitch) {
  929.         double x;
  930.         (void) sscanf(v, "%le", &x);
  931.         bcopy((char *) &x, 
  932.           (char *) (segment[currentSegment].mem + LC[currentSegment]),
  933.           size);
  934.     }
  935.     else {
  936.         SpurDoubleFloat x;
  937.         x = toDoubleIEEE(v,l);
  938.         bcopy((char *) &x, 
  939.           (char *) (segment[currentSegment].mem + LC[currentSegment]),
  940.           size);
  941.     }
  942.     }
  943.  
  944.     LC[currentSegment] += size;
  945. }
  946.  
  947. int
  948. segmentToType(segment)
  949.      int segment;
  950.      /* Return symbol type (see a.out.h) for given segment number */
  951. {
  952.     switch (segment) {
  953.     case RP_SEG0:
  954.     case RP_SEG0+1:
  955.     case RP_SEG0+2:
  956.     return N_TEXT;
  957.     case RP_SEG0+3:
  958.     case RP_SEG0+4:
  959.     case RP_SEG0+5:
  960.     return N_DATA;
  961.     case RP_SEG0+6:
  962.     return N_BSS;
  963.     case RP_SEG0+7:
  964.     case RP_SEG0+8:
  965.     return N_SDATA;
  966.     case RP_SEG0+9:
  967.     return N_SBSS;
  968.     default:
  969.     ErrorMsg "Internal assembler error: bad segment type." EndMsg;
  970.     exit2(1);
  971.     return 0;
  972.     }
  973. }
  974.  
  975. void
  976. setSymDefn(sym, e)
  977.      symbolType *sym;
  978.      exprType *e;
  979.      /* Define symbol sym to have value given by e */
  980. {
  981.     int stype = sym -> type & N_TYPE;
  982.     if (stype != N_UNDF && stype != N_COMM && stype != N_SCOMM) {
  983.     ErrorMsg
  984.         "Symbol %s previously defined.", sym -> string
  985.         EndMsg;
  986.     return;
  987.     }
  988.     if (e -> class == MANIFEST_INT) {
  989.     sym -> type = N_ABS | (sym -> type & ~N_TYPE);
  990.     sym -> value = e -> v.value;
  991.     }
  992.     else if (e -> class == SYM_EXPR && e -> v.sym -> id < NUM_ASM_SEGS) {
  993.     sym -> type = segmentToType(e -> v.sym -> id) | (sym->type & ~N_TYPE);
  994.     sym -> value = e -> offset;
  995.     sym -> segment = e -> v.sym -> id;
  996.     }
  997.     else {
  998.     sym -> type = N_UNDF | (sym-> type & ~N_TYPE);
  999.     sym -> value = 0;
  1000.     emitReloc(RP_SYMBOLS,
  1001.           (unsigned int) ((sym -> id) * sizeof(struct nlist)), 
  1002.           RP_32, 0, e);
  1003.     }
  1004. }
  1005.  
  1006. void
  1007. setSymCommDefn(sym, e, isShared)
  1008.      symbolType *sym;
  1009.      exprType *e;
  1010.      bool isShared;
  1011.      /* Define symbol sym to be a global bss symbol of size given by e. 
  1012.       * Place in shared area if isShared, and otherwise make private. */
  1013. {
  1014.     int type = sym -> type & N_TYPE;
  1015.     unsigned int val;
  1016.     int commType = N_EXT | (isShared ? N_SCOMM : N_COMM);
  1017.  
  1018.     if (e -> class != MANIFEST_INT) {
  1019.     ErrorMsg "Absolute expression required for (s)comm." EndMsg;
  1020.     }
  1021.     val = (e -> v.value + 7) & ~0x7;
  1022.     switch (type) {
  1023.     case N_UNDF:
  1024.     sym -> type = commType;
  1025.     sym -> value = val;
  1026.     break;
  1027.     case N_COMM:
  1028.     case N_SCOMM:
  1029.     if (type != commType) 
  1030.     ErrorMsg "Common symbol redefined for different kind of segment." 
  1031.         EndMsg;
  1032.     if (val > sym -> value) 
  1033.         sym -> value = val;
  1034.     break;
  1035.     default:
  1036.     break;
  1037.     }
  1038. }
  1039.     
  1040.  
  1041. void
  1042. setSymLcommDefn(sym, e, isShared)
  1043.      symbolType *sym;
  1044.      exprType *e;
  1045.      bool isShared;
  1046.      /* Define symbol sym to be in the bss region of size given by e. Use
  1047.       * shared bss if isShared, and otherwise private bss. */
  1048. {
  1049.     int oldSegment = currentSegment;
  1050.     
  1051.     currentSegment = isShared ? SBSS_SEG : BSS_SEG;
  1052.     if (e -> class != MANIFEST_INT) {
  1053.     ErrorMsg "Absolute expression required for (s)lcomm." EndMsg;
  1054.     }
  1055.     else {
  1056.     setAlignment(3);
  1057.     DefineLabel(sym);
  1058.     LC[currentSegment] += e -> v.value;
  1059.     if (LC[currentSegment] > segmentSize[currentSegment])
  1060.         segmentSize[currentSegment] = LC[currentSegment];
  1061.     }
  1062.     currentSegment = oldSegment;
  1063. }
  1064.  
  1065. void
  1066. DefineLabel(sym)
  1067.      symbolType *sym;
  1068.      /* Define sym as label at current position in current region */
  1069. {
  1070.     int stype = sym -> type & N_TYPE;
  1071.     if (stype != N_UNDF && stype != N_COMM && stype != N_SCOMM) {
  1072.     ErrorMsg
  1073.         "Label %s previously defined.", sym->string
  1074.     EndMsg;
  1075.     return;
  1076.     }
  1077.     sym -> type = segmentToType(currentSegment) | (sym -> type & ~N_TYPE);
  1078.     sym -> value = LC[currentSegment];
  1079.     sym -> segment = currentSegment;
  1080. }
  1081.  
  1082. void
  1083. setGlobalSym(sym)
  1084.      symbolType *sym;
  1085.      /* Make sym an exported (or imported) symbol. */
  1086. {
  1087.     sym -> type |= N_EXT;
  1088. }
  1089.  
  1090. void
  1091. setAlignment(n)
  1092.      unsigned int n;
  1093.      /* Align current LC to 2**n boundary. */
  1094. {
  1095.     if (n > 3) {
  1096.     WarningMsg "Warning: .align argument greater than 3." EndMsg;
  1097.     }
  1098.     if (n > 31) n = 31;
  1099.     n = 1 << n;
  1100.     LC[currentSegment] = (LC[currentSegment] + n - 1 ) & ~(n-1);
  1101.     checkSeg(segment[currentSegment], LC[currentSegment]);
  1102. }
  1103.  
  1104. void
  1105. emitRRxInst(op, rd, rs1, rc)
  1106.      unsigned int op;
  1107.      operandType rd,rs1,rc;
  1108.      /* Emit an RRR or RRI format instruction with destination rd, first source
  1109.       * register rs1, second source register or immediate rc, and opcode op.
  1110.       */
  1111. {
  1112.     unsigned int inst;
  1113.  
  1114.     if (op == nopOpcode && op & disallowedOpcodeMask)
  1115.         op = add_ntOpcode;
  1116.     checkOpcode(op);
  1117.  
  1118.     inst = op<<opCodePosn | rd.number<<destPosn | rs1.number<<src1Posn;
  1119.  
  1120.     if (rc.type == REG) {
  1121.     inst |= rc.number<<src2Posn;
  1122.     }
  1123.     else if (rc.expr -> class == MANIFEST_INT && 
  1124.          !isValidConstant(rc.expr -> v.value)) {
  1125.     ErrorMsg
  1126.         "Immediate constant out of range."
  1127.     EndMsg;
  1128.     }
  1129.     else {    
  1130.     inst |= immedFlag;
  1131.     if (rc.expr -> class == MANIFEST_INT)
  1132.         inst |= (rc.expr -> v.value & immedMask);
  1133.     else
  1134.         emitReloc(currentSegment, LC[currentSegment], RP_LOW14,
  1135.               0, rc.expr);
  1136.     }
  1137.     
  1138.     emitInst(inst);
  1139. }
  1140.  
  1141. void
  1142. emitStoreInst(op, from, to, sc)
  1143.      unsigned int op;
  1144.      operandType from, to;
  1145.      exprType *sc;
  1146.      /* Emit store-format instruction op with given operands. */
  1147. {
  1148.     unsigned int inst;
  1149.     unsigned int lowPart, highPart;
  1150.  
  1151.     checkOpcode(op);
  1152.  
  1153.     inst = op<<opCodePosn | from.number<<src2Posn | immedFlag 
  1154.        | to.number << src1Posn;
  1155.  
  1156.     if (sc -> class == MANIFEST_INT) {
  1157.     lowPart = (sc -> v.value) & immedMask;
  1158.     highPart = (sc -> v.value) & (immedSign | ~immedMask);
  1159.  
  1160.     inst |=  lowPart & lowStoreMask 
  1161.            | lowPart << (storeHighPosn - src2Posn) & highStoreMask;
  1162.  
  1163.     if (isValidConstant(sc -> v.value)) {
  1164.         inst |= to.number << src1Posn
  1165.           | (sc -> v.value) & immedSign << (storeHighPosn - src2Posn);
  1166.     }
  1167.     else {
  1168.         ErrorMsg
  1169.         "Immediate constant out of range."
  1170.         EndMsg;
  1171.     }
  1172.     }        
  1173.     else {
  1174.     emitReloc(currentSegment, LC[currentSegment], RP_SCONS,
  1175.           0, 
  1176.           sc);
  1177.     }
  1178.     emitInst(inst);
  1179. }
  1180.  
  1181. void
  1182. emitRxCmpInst(op, cond, rs1, cc, instAddr, trap)
  1183.      unsigned int op,cond;
  1184.      operandType rs1, cc;
  1185.      exprType *instAddr;
  1186.      bool trap;
  1187.      /* Generate compare instruction, with jump target instAddr.  If instAddr 
  1188.       * is NULL, the offset field of the instruction is set to 0.  Otherwise, 
  1189.       * if trap is TRUE, the offset field of the instruction is set to the 
  1190.       * value of expression instAddr.  Otherwise, the offset is set to a 
  1191.       * pc-relative word offset from instAddr. */
  1192.     unsigned int inst;
  1193.  
  1194.     checkOpcode(op);
  1195.  
  1196.     inst = op<<opCodePosn | cond<<condPosn | rs1.number<<src1Posn;
  1197.  
  1198.     if (cc.type == REG) 
  1199.     inst |= cc.number<<src2Posn;
  1200.     else if (cond == eq_tag_immed_code || cond == ne_tag_immed_code) {
  1201.     unsigned int val = cc.expr -> v.value;
  1202.  
  1203.     if (val > (1<<6)-1) {
  1204.         ErrorMsg "Tag immediate constant value %d out of range.", val 
  1205.         EndMsg;
  1206.     }
  1207.     else 
  1208.         inst |= val << tagImmedPosn;
  1209.     }
  1210.     else {
  1211.     unsigned int val = cc.expr -> v.value;
  1212.  
  1213.     inst |= immedFlag;
  1214.     if (val > (1<<5)-1) {
  1215.         ErrorMsg "Compare immediate operand value %d out of range.", val
  1216.         EndMsg;
  1217.     }
  1218.     else
  1219.         inst |= val << shortImmedPosn;
  1220.     }
  1221.  
  1222.     if (instAddr != nullExpr) {
  1223.     if (trap) {
  1224.         emitReloc(currentSegment, LC[currentSegment], RP_LOW9, 
  1225.               0, instAddr);
  1226.     }
  1227.     else
  1228.         emitReloc(currentSegment, LC[currentSegment], RP_LOW9,
  1229.               1,
  1230.               consBinaryExpr('-', instAddr, pointExpr()));
  1231.     }
  1232.  
  1233.     emitInst(inst);
  1234. }
  1235.  
  1236. void
  1237. emitCmpTagInst(op, cond, rs1, tc, instAddr, trap)
  1238.      unsigned int op, cond;
  1239.      operandType rs1;
  1240.      exprType *tc, *instAddr;
  1241.      bool trap;
  1242.      /* Emit tag compare instruction. InstAddr is treated as for 
  1243.     emitRxCmpInst. */
  1244. {
  1245.     unsigned int inst;
  1246.     unsigned int val = tc -> v.value;
  1247.  
  1248.     checkOpcode(op);
  1249.  
  1250.     inst = op<<opCodePosn | cond<<condPosn | rs1.number<<src1Posn;
  1251.  
  1252.     if (val > (1<<6)-1) {
  1253.     ErrorMsg "Tag immediate constant value %d out of range.", val EndMsg;
  1254.     }
  1255.     else
  1256.     inst |= val << tagImmedPosn;
  1257.  
  1258.     if (instAddr != nullExpr) {
  1259.     if (trap) {
  1260.         emitReloc(currentSegment, LC[currentSegment], RP_LOW9, 
  1261.               0,
  1262.               instAddr);
  1263.     }
  1264.     else
  1265.         emitReloc(currentSegment, LC[currentSegment], RP_LOW9,
  1266.               1,
  1267.               consBinaryExpr('-', instAddr, pointExpr()));
  1268.     }
  1269.  
  1270.     emitInst(inst);
  1271. }
  1272.  
  1273. void
  1274. emitJumpInst(op, instAddr)
  1275.      unsigned int op;
  1276.      exprType *instAddr;
  1277.      /* Emit jump-style op instruction with given word address as target. */
  1278. {
  1279.     unsigned int inst;
  1280.  
  1281.     checkOpcode(op);
  1282.  
  1283.     inst = op<<jumpOpCodePosn;
  1284.     emitReloc(currentSegment, LC[currentSegment], RP_LOW28, 1, 
  1285.           instAddr);
  1286.  
  1287.     emitInst(inst);
  1288. }
  1289.  
  1290. void
  1291. emitReloc(segNum, offset, bits, wordp, addr)
  1292.      int segNum, bits, wordp;
  1293.      unsigned int  offset;
  1294.      exprType *addr;
  1295.      /* Emit relocation directive for word at given offset from segment 
  1296.       * designated by segNum.  Bits indicates bits to be affected, as indicated
  1297.       * in r_length field for the relocation_info structure.  Wordp is either 
  1298.       * 1 or 0. Addr is the expression whose value is 
  1299.       * to be placed in the indicated word.  It is assumed that the value of
  1300.       * the location to be modified is 0 in the file.
  1301.       */
  1302. {
  1303.     struct relocation_info *item;
  1304.     checkSeg(reloc, relocSize+sizeof(struct relocation_info));
  1305.     item = (struct relocation_info *) (reloc.mem + relocSize);
  1306.     item->r_address = offset;
  1307.     item->r_segment = segNum;
  1308.     item->r_word = wordp;
  1309.     item->r_length = bits;
  1310.     item->r_extra = 0;
  1311.     if (addr -> class == SYM_EXPR && addr -> offset == 0) {
  1312.     item->r_expr = addr -> v.sym -> id;
  1313.     item->r_reltype = RP_RSYM;
  1314.     }
  1315.     else {
  1316.         item->r_expr = emitConvertedExpr(addr);
  1317.     item->r_reltype = RP_REXP;
  1318.     }
  1319.  
  1320.     relocSize += sizeof(struct relocation_info);
  1321. }
  1322.  
  1323.  
  1324. #define emitExprSyl(x,y) { \
  1325.         checkSeg(relocExpr,  relocExprSize+sizeof(union reloc_expr)); \
  1326.         EO_SET_SYL2(*(union reloc_expr *) (relocExpr.mem + relocExprSize),\
  1327.             x, y); \
  1328.         relocExprSize += sizeof(union reloc_expr); \
  1329.         }
  1330. #define emitExprVal(x) { \
  1331.         checkSeg(relocExpr,  relocExprSize+sizeof(union reloc_expr)); \
  1332.         ((union reloc_expr *) (relocExpr.mem + relocExprSize)) -> re_value = (x); \
  1333.         relocExprSize += sizeof(union reloc_expr); \
  1334.         }
  1335.  
  1336. unsigned int
  1337. emitConvertedExpr(e)
  1338.      exprType *e;
  1339.      /* Convert e to object file format and put into expression area. Return
  1340.       * offset into expression area. */
  1341. {
  1342.     unsigned int result = relocExprSize;
  1343.  
  1344.     switch (e -> class) {
  1345.     case MANIFEST_INT:
  1346.     emitExprSyl(EO_INT, 0);
  1347.     emitExprVal(e -> v.value);
  1348.     break;
  1349.     case SYM_EXPR:
  1350.     emitExprSyl(EO_SYM, e -> v.sym -> id);
  1351.     emitExprVal(e -> offset);
  1352.     break;
  1353.     case BINARY_EXPR:
  1354.     {
  1355.         int cmnd;
  1356.         switch (e -> v.opcode) {
  1357.         case '+': cmnd = EO_PLUS;
  1358.         break;
  1359.         case '-': cmnd = EO_SUB;
  1360.         break;
  1361.         case '*': cmnd = EO_MULT;
  1362.         break;
  1363.         case '/': cmnd = EO_DIV;
  1364.         break;
  1365.         case LSHIFT: cmnd = EO_SLL;
  1366.         break;
  1367.         case RSHIFT: cmnd = EO_SRL;
  1368.         break;
  1369.         case '&': cmnd = EO_AND;
  1370.         break;
  1371.         case '|': cmnd = EO_OR;
  1372.         break;
  1373.         case '^': cmnd = EO_XOR;
  1374.         break;
  1375.         default:
  1376.         ErrorMsg "Internal assembler error: bad operator." EndMsg;
  1377.         exit2(1);
  1378.         }
  1379.         emitExprSyl(cmnd, 0);
  1380.         (void) emitConvertedExpr(e -> left);
  1381.         (void) emitConvertedExpr(e -> right);
  1382.     }
  1383.     break;
  1384.     case UNARY_EXPR:
  1385.     {
  1386.         int cmnd;
  1387.  
  1388.         switch (e -> v.opcode) {
  1389.         case '-': cmnd = EO_MINUS;
  1390.         break;
  1391.         case '~': cmnd = EO_COMP;
  1392.         break;
  1393.         default:
  1394.         ErrorMsg "Internal assembler error: bad operator." EndMsg;
  1395.         exit2(1);
  1396.         }
  1397.         emitExprSyl(cmnd, 0);
  1398.         (void) emitConvertedExpr(e -> left);
  1399.     }
  1400.     break;
  1401.     }
  1402.  
  1403.     return result;
  1404. }
  1405.  
  1406. unsigned int
  1407. emitString(s)
  1408.      char *s;
  1409.      /* Place string s in string area and return offset. */
  1410. {
  1411.     unsigned int start = stringsSize;
  1412.     int len;
  1413.  
  1414.     if (s == NULL || s[0] == '\0') return 0;
  1415.  
  1416.     len = strlen(s);
  1417.     checkSeg(strings, stringsSize+len+1);
  1418.     (void) strcpy((char *) (strings.mem + stringsSize), s);
  1419.     stringsSize += len+1;
  1420.     return start;
  1421. }
  1422.  
  1423. void
  1424. emitSymbol(sym, dest)
  1425.      symbolType *sym;
  1426.      struct nlist *dest;
  1427.      /* Convert sym into object file form and put in dest. */
  1428. {
  1429.     int stype = sym -> type & N_TYPE;
  1430.  
  1431.     dest -> n_un.n_strx = emitString(sym -> string);
  1432.     dest -> n_type = 
  1433.     sym -> type == N_UNDF ? N_UNDF | N_EXT : sym -> type;
  1434.     dest -> n_other = sym -> other, dest -> n_desc = sym -> desc;
  1435.     dest -> n_value = sym -> value;
  1436.     if (stype == N_TEXT || stype == N_DATA || stype == N_BSS ||
  1437.     stype == N_SDATA || stype == N_SBSS)
  1438.         dest -> n_value += segmentStart[sym -> segment];
  1439. }
  1440.  
  1441. void
  1442. emitAllSymbols()
  1443.      /* Create object file symbol table in symbols. Set symbolSize. */
  1444. {
  1445.     symbolType *sym;
  1446.     struct nlist *objSym;
  1447.  
  1448.     symbolsSize = nextId * sizeof(struct nlist);
  1449.     symbols = (struct nlist *) malloc((unsigned) symbolsSize);
  1450.     if (symbols == NULL) {
  1451.     ErrorMsg "Fatal error.  Insufficient space." EndMsg;
  1452.     }
  1453.     
  1454.     for (sym = firstSym; sym != NULL; sym = sym -> next) {
  1455.     objSym = symbols + sym -> id;
  1456.     emitSymbol(sym, objSym);
  1457.     }
  1458. }
  1459.  
  1460. void
  1461. joinSegments()
  1462.      /* Compute positions of start of TEXTn, DATAn, BSS, SDATAn, SBSS
  1463.       * in segmentStart, rounded up to multiples of 8. */
  1464. {
  1465.     unsigned int place = 0;
  1466.     int i;
  1467.  
  1468.     for (i = 0; i < NUM_ASM_SEGS; i++) {
  1469.     int seg = RP_SEG0 + i;
  1470.     if (LC[seg] > segmentSize[seg]) segmentSize[seg] = LC[seg];
  1471.     if (seg == FIRST_SHARED_DATA_SEG)
  1472.         place = N_SDATADDR(0);
  1473.     segmentStart[seg] = place;
  1474.     segmentSize[seg] = 
  1475.         (segmentSize[seg] + SEGMENT_ALIGN - 1) & ~(SEGMENT_ALIGN-1);
  1476.     place += segmentSize[seg];
  1477.     }
  1478. }
  1479.  
  1480. void
  1481. createHeader(head)
  1482.      struct exec *head;
  1483.      /* Set *head to the appropriate header, assuming segmentSize is set 
  1484.       * correctly. */
  1485. {
  1486.     head -> a_magic = OMAGIC;
  1487.     head -> a_bytord = 0x01020304;
  1488.     head -> a_text = segmentStart[FIRST_DATA_SEG];
  1489.     head -> a_data = segmentStart[BSS_SEG] - segmentStart[FIRST_DATA_SEG];
  1490.     head -> a_sdata = 
  1491.     segmentStart[SBSS_SEG] - segmentStart[FIRST_SHARED_DATA_SEG];
  1492.     head -> a_bss =  segmentSize[BSS_SEG];
  1493.     head -> a_sbss = segmentSize[SBSS_SEG];
  1494.     head -> a_syms = symbolsSize;
  1495.     head -> a_entry = 0;
  1496.     head -> a_rsize = relocSize;
  1497.     head -> a_expsize = relocExprSize;
  1498.     head -> a_padding = 0;
  1499. }
  1500.  
  1501. void
  1502. writeRegion(fd, p, size)
  1503.      int fd;
  1504.      unsigned int size;
  1505.      char *p;
  1506.      /* Write region of storage of size bytes starting at p to fd. */
  1507. {
  1508.     if (size == 0) return;
  1509.     if (size != write(fd, (char *) p, (int) size)) {
  1510.     ErrorMsg "Write failed." EndMsg;
  1511.     exit2(1);
  1512.     }
  1513. }
  1514.  
  1515. void
  1516. writeObject(fd)
  1517.      int fd;
  1518.      /* Write object file on file fd.  Assumes that segments, segmentSize, 
  1519.       * reloc, relocExpr, relocSize, relocExprSize, and firstSym are set.  Sets
  1520.       * segmentStart, strings, symbols, symbolsSize, stringsSize. Destructively
  1521.       * modifies all of these data. */
  1522. {
  1523.     struct exec header;
  1524.     int i;
  1525.  
  1526.     joinSegments();
  1527.     emitAllSymbols();
  1528.     createHeader(&header);
  1529.     
  1530.     *((int *) strings.mem) = stringsSize;
  1531.     
  1532.     writeRegion(fd, (char *) &header, sizeof(header));
  1533.     for (i = 0; i < NUM_ASM_SEGS; i++) {
  1534.     int seg = RP_SEG0 + i;
  1535.     if (seg != BSS_SEG && seg != SBSS_SEG)
  1536.         writeRegion(fd, segment[seg].mem, segmentSize[seg]);
  1537.     }
  1538.     writeRegion(fd, reloc.mem, relocSize);
  1539.     writeRegion(fd, relocExpr.mem, relocExprSize);
  1540.     writeRegion(fd, (char *) symbols, symbolsSize);
  1541.     writeRegion(fd, strings.mem, stringsSize);
  1542. }
  1543.  
  1544.         /* Initialization */
  1545. void
  1546. initSas()
  1547. {
  1548.     int i;
  1549.  
  1550.     for (i = 0; i < NUM_ASM_SEGS; i++) {
  1551.     int seg = RP_SEG0 + i;
  1552.     symbolType *sym =
  1553.         segmentSym[seg] = (symbolType *) malloc(sizeof(symbolType));
  1554.  
  1555.     initSegment(&segment[seg], seg == BSS_SEG || seg == SBSS_SEG);
  1556.     segmentSize[seg] = LC[seg] = 0;
  1557.     sym -> id = -1;
  1558.     assignId(sym);
  1559.     sym -> type = segmentToType(seg);
  1560.     sym -> string[0] = '\0';
  1561.     sym -> segment = seg;
  1562.     sym -> value = 0;
  1563.     }
  1564.     
  1565.     initSegment(&reloc, FALSE);
  1566.     relocSize = 0;
  1567.     initSegment(&relocExpr, FALSE);
  1568.     relocExprSize = 0;
  1569.     initSegment(&strings, FALSE);
  1570.     stringsSize = sizeof(int);
  1571.  
  1572.     currentSegment = FIRST_TEXT_SEG;
  1573.  
  1574.     initTempLabels();
  1575. }
  1576.             /* Command line processing, etc. */
  1577.  
  1578. static int waitPid = -1;        /* Process id for preprocessor. */
  1579. int linecount = 1;        /* Current line number */
  1580. char filename[MAXFILENAMELENGTH+1];
  1581.                                 /* Name of current input file */
  1582.  
  1583. int
  1584. waitForChild()
  1585.      /* Wait for child process, if any, and return its status, or 0 if none. */
  1586. {
  1587.     int pid;
  1588.     union wait status;
  1589.     
  1590.     if (waitPid == -1) return 0;
  1591.  
  1592.     for (pid = -1; pid != waitPid; pid = wait(&status));
  1593.     waitPid = -1;
  1594.     return (status.w_T.w_Retcode);
  1595. }
  1596.  
  1597. void
  1598. exit2(status)
  1599.      int status;
  1600.      /* Wait for waitPid to finish and then exit with given status. */
  1601. {
  1602.     (void) fclose(stdin);
  1603.  
  1604.     (void) waitForChild();
  1605.     exit(status);
  1606. }
  1607.  
  1608. void
  1609. setInput(f, preprocessp,args,numArgs)
  1610.      char *f;
  1611.      int preprocessp, numArgs;
  1612.      char *args[];
  1613.      /* Set stdin to input file f.  If preprocessp, then this input consists of
  1614.     the output of cpp given file name f (stdin if f is ""). Otherwise, f or
  1615.     stdin is used as the input file directly.  Args[1 .. numArgs] supply
  1616.     additional arguments to preprocessor.  The array args may be modified.
  1617.     Sets waitPid to pid of process or -1. */
  1618. {
  1619.     int filedes[2];
  1620.  
  1621.     waitPid = -1;
  1622.     if (preprocessp) {
  1623.     if (pipe(filedes) == -1) {
  1624.         ErrorMsg "Failed to invoke preprocessor." EndMsg;
  1625.         exit(1);
  1626.     }
  1627.     if (f[0] != '\0' && access(f, F_OK | R_OK)) {
  1628.         ErrorMsg "Can't open file %s.", f EndMsg;
  1629.         exit(1);
  1630.     }
  1631.     args[numArgs+1] = f;
  1632.     args[numArgs+2] = NULL;
  1633.     args[0] = PREPROCESSOR;
  1634.     waitPid = vfork();
  1635.     if (waitPid == 0) {
  1636.         (void) close(1);
  1637.         (void) dup(filedes[1]);
  1638.         (void) close(filedes[0]);
  1639.         (void) close(filedes[1]);
  1640.         (void) execv(PREPROCESSOR, args);
  1641.         exit(1);    /* Shouldn't get here. */
  1642.     }
  1643.     if (waitPid == -1) {
  1644.         ErrorMsg "Failed to invoke preprocessor." EndMsg;
  1645.         exit(1);
  1646.     }
  1647.     (void) close(0);
  1648.     (void) dup(filedes[0]);
  1649.     (void) close(filedes[0]);
  1650.     (void) close(filedes[1]);
  1651.     }
  1652.     else {
  1653.     if (f[0] != '\0' && freopen(f, "r", stdin) == NULL) {
  1654.         ErrorMsg "Open failed for file %s.", f EndMsg;
  1655.         exit(1);
  1656.     }
  1657.     }
  1658. }
  1659.  
  1660. main(argc, argv)
  1661.      int argc;
  1662.      char *argv[];
  1663. {
  1664.     int i;
  1665.     char outFileName[MAXFILENAMELENGTH+1];
  1666.     char *preprocessArgs[MAXPREPROCESSARGS];        /* Arguments to /lib/cpp */
  1667.     int numPreprocessArgs = 0;
  1668.     int outFd;
  1669.     bool preprocess = FALSE;    /* TRUE indicates preprocessing needed. */
  1670.     bool load = TRUE;        /* TRUE indicates post-processing by sld 
  1671.                    needed. */
  1672.     bool preserveL = FALSE;    /* TRUE indicates local labels beginning
  1673.                  * with L should be preserved. */
  1674.  
  1675.     errorCount = 0;
  1676.     disallowedOpcodeMask = simulatorOpMask;
  1677.     nativeFloatSwitch = FALSE;
  1678.     filename[0] = '\0';
  1679.     outFileName[0] = '\0';
  1680.  
  1681.     for (i = 1; i < argc; i++) {
  1682.     char *s;
  1683.  
  1684.     if (argv[i][0] == '-') {
  1685.         switch (argv[i][1]) {
  1686.         case 'o':
  1687.         if (argc > i+1)
  1688.             (void) strcpy(outFileName, argv[++i]);
  1689.         else {
  1690.             ErrorMsg "Invalid -o switch." EndMsg;
  1691.             exit(1);
  1692.         }
  1693.         break;
  1694.         case 'f':        /* Allow "fake" simulator operations */
  1695.         disallowedOpcodeMask &= ~simulatorOpMask;
  1696.         break;        
  1697.         case 'F':
  1698.         nativeFloatSwitch = TRUE;
  1699.         break;
  1700.         case 'L':
  1701.         preserveL = TRUE;
  1702.         break;
  1703.         case 'p':
  1704.         preprocess = TRUE;
  1705.         break;
  1706.         case 'I':
  1707.         case 'D':
  1708.         case 'U':
  1709.         preprocessArgs[1+numPreprocessArgs++] = argv[i];
  1710.         preprocess = TRUE;
  1711.         break;
  1712.         case 'a':
  1713.         load = FALSE;
  1714.         break;
  1715.         default:
  1716.         ErrorMsg "Unknown command line option %s.", argv[i] EndMsg;
  1717.         exit(1);
  1718.         }
  1719.     }
  1720.     else {
  1721.         if (filename[0] != '\0') {
  1722.         ErrorMsg "Only one file allowed." EndMsg;
  1723.         exit(1);
  1724.         }
  1725.         (void) strncpy(filename, argv[i], MAXFILENAMELENGTH);
  1726.         if (outFileName[0] == '\0') {
  1727.         for (s = filename + strlen(filename); 
  1728.              s != filename && s[-1] != '/'; s--);
  1729.         (void) strcpy(outFileName, s);
  1730.         if (outFileName[strlen(outFileName) - 2] == '.')
  1731.             outFileName[strlen(outFileName)-1] = 'o';
  1732.         else (void) strcat(outFileName, ".o");
  1733.         }
  1734.     }
  1735.     }
  1736.     if (outFileName[0] == '\0') 
  1737.     (void) strcpy(outFileName, "a.out");
  1738.  
  1739.     setInput(filename,preprocess,preprocessArgs, numPreprocessArgs);
  1740.     initLexer();
  1741.     initParser();
  1742.     initSas();
  1743.     (void) yyparse();
  1744.     resetTempLabels();
  1745.     (void) fclose(stdin);
  1746.     (void) waitForChild();
  1747.  
  1748.     if (errorCount != 0) 
  1749.     exit(1);
  1750.     
  1751.     outFd = open(outFileName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  1752.     if (outFd == -1) {
  1753.     ErrorMsg "Failed to open file %s.", outFileName EndMsg;
  1754.     exit(1);
  1755.     }
  1756.     writeObject(outFd);
  1757.     
  1758.     if (errorCount != 0) {
  1759.     (void) ftruncate(outFd,0);
  1760.     exit(1);
  1761.     }
  1762.     
  1763.     (void) close(outFd);
  1764.     
  1765.     if (load) {
  1766.     char *loadArgs[8];
  1767.     int i = 0;
  1768.     
  1769.     loadArgs[i++] = LOADER;
  1770.     loadArgs[i++] = "-r";
  1771.     loadArgs[i++] = "-o"; loadArgs[i++] = outFileName;
  1772.     if (!preserveL) loadArgs[i++] = "-X";
  1773.     loadArgs[i++] = outFileName;
  1774.     loadArgs[i++] = NULL;
  1775.     
  1776.     (void) fflush(stdout);
  1777.     (void) fflush(stderr);
  1778.     (void) execv(LOADER, loadArgs);
  1779.     ErrorMsg "Sld post-processing failed." EndMsg;
  1780.     exit(1);
  1781.     }
  1782.     
  1783.     exit(0);
  1784. }
  1785.